package com.example.service.shopping;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;

import com.example.common.enums.ResultCodeEnum;
import com.example.common.enums.RoleEnum;
import com.example.exception.CustomException;
import com.example.mapper.appointment.UserMapper;
import com.example.mapper.shopping.*;
import com.example.mapper.tribune.CollectMapper;
import com.example.model.dto.HospitalDto;
import com.example.model.dto.MedicinesDto;
import com.example.model.dto.RelateDTO;
import com.example.model.entity.appointment.User;
import com.example.model.entity.medical.Hospital;
import com.example.model.entity.other.Account;
import com.example.model.entity.shopping.*;
import com.example.model.entity.tribune.Collect;
import com.example.model.vo.CartVO;
import com.example.model.vo.MedicinesVO;
import com.example.model.vo.UserCommentVO;
import com.example.utils.TokenUtils;
import com.example.utils.UserCF;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 药品信息表业务处理
 **/
@Service
public class MedicinesService {

    @Resource
    private MedicinesMapper medicinesMapper;
    @Resource
    private MedicinesStyleMapper medicinesStyleMapper;
    @Resource
    private MedicinesTypeMapper medicinesTypeMapper;
    @Resource
    private UserMapper userMapper;
    @Resource
    private CollectMapper collectMapper;
    @Resource
    private UserCommentMapper userCommentMapper;
    @Resource
    private CartMapper cartMapper;
    @Resource
    private OrderMapper orderMapper;

    /**
     * 新增
     */
    public void add(Medicines medicines) {
        Account currentUser = TokenUtils.getCurrentUser();
        if(RoleEnum.BUSINESS.name().equals(currentUser.getRole())){
            medicines.setBusinessId(currentUser.getId());
        }
        medicinesMapper.insert(medicines);
    }

    /**
     * 删除
     */
    public void deleteById(Integer id) {
        medicinesMapper.deleteById(id);
    }

    /**
     * 批量删除
     */
    public void deleteBatch(List<Integer> ids) {
        for (Integer id : ids) {
            medicinesMapper.deleteById(id);
        }
    }

    /**
     * 修改
     */
    public void updateById(Medicines medicines) {
        medicinesMapper.updateById(medicines);
    }

    /**
     * 根据ID查询
     */
    public Medicines selectById(Integer id) {
        return medicinesMapper.selectById(id);
    }

    /**
     * 查询所有
     */
    public List<MedicinesVO> selectAll(Medicines medicines) {
        Account currentUser = TokenUtils.getCurrentUser();
        if(RoleEnum.BUSINESS.name().equals(currentUser.getRole())){
            medicines.setBusinessId(currentUser.getId());
        }
        List<MedicinesVO> medicinesVOList = medicinesMapper.selectAll(medicines);
        return getMedicines(medicinesVOList);
    }

    /**
     * 分页查询
     */
    public PageInfo<Medicines> selectPage(Medicines medicines, Integer pageNum, Integer pageSize) {
        Account currentUser = TokenUtils.getCurrentUser();
        if(RoleEnum.BUSINESS.name().equals(currentUser.getRole())){
            medicines.setBusinessId(currentUser.getId());
        }
        PageHelper.startPage(pageNum, pageSize);
        List<MedicinesVO> medicinesVOList = medicinesMapper.selectAll(medicines);
        medicinesVOList.forEach(medicinesVO -> {
            Integer medicinesId = medicinesVO.getId();
            List<MedicinesStyle> medicinesStyleList = medicinesStyleMapper.selectByMedicinesId(medicinesId);
            medicinesVO.setMedicinesStyleList(medicinesStyleList);
        });
        return PageInfo.of(medicinesVOList);
    }

    public void updateBatch(MedicinesDto medicinesDto) {
        for (Integer id : medicinesDto.getIds()) {
            String status = medicinesDto.getStatus();
            Medicines medicines = medicinesMapper.selectById(id);
            medicines.setStatus(status);
            medicinesMapper.updateById(medicines);
        }
    }

    public MedicinesVO selectDetailById(Integer medicinesId) {
        return medicinesMapper.selectDetailById(medicinesId);
    }
    public List<MedicinesVO> selectByBusinessId(Integer businessId) {
        return medicinesMapper.selectDetailByBusinessId(businessId);
    }

    public List<MedicinesVO> selectByTypeId(Integer typeId) {
        if (typeId == null || typeId <= 0) {
            throw new CustomException(ResultCodeEnum.PARAM_ERROR);
        }
        List<MedicinesVO> medicinesVOList = medicinesMapper.selectByTypeId(typeId);
        return getMedicines(medicinesVOList);
    }
    public List<MedicinesVO> selectByTypeName(String typeName) {
        MedicinesType medicinesType = medicinesTypeMapper.selectByName(typeName);
        List<MedicinesVO> medicinesVOList = medicinesMapper.selectByTypeId(medicinesType.getId());
        return getMedicinesVOS(medicinesVOList);
    }


    public List<MedicinesVO> getMedicinesVOS(List<MedicinesVO> medicinesVOList) {
        return getMedicines(medicinesVOList);
    }


    public List<MedicinesVO> getMedicines(List<MedicinesVO> medicinesVOList) {
        medicinesVOList.forEach(medicinesVO -> {
            Integer medicinesId = medicinesVO.getId();
            List<MedicinesStyle> medicinesStyleList = medicinesStyleMapper.selectByMedicinesId(medicinesId);
            medicinesVO.setMedicinesStyleList(medicinesStyleList);
        });
        medicinesVOList.sort((o1, o2) -> o2.getCount() - o1.getCount());
        return medicinesVOList;
    }


    public Integer selectMedicinesByName(String name) {
        return medicinesMapper.selectMedicinesByName(name);
    }

    public List<Medicines> recommend() {
        Account currentUser = TokenUtils.getCurrentUser();
        if (ObjectUtil.isEmpty(currentUser)) {
            // 没有用户登录
            return new ArrayList<>();
        }
        // 用户的哪些行为可以认为他跟商品产生了关系？收藏、加入购物车、下单、评论
        // 1. 获取所有的收藏信息
        List<Collect> allCollects = collectMapper.selectAllOKCollect(null);
        // 2. 获取所有的购物车信息
        List<CartVO> allCarts = cartMapper.selectAllOKCart(null);
        // 3. 获取所有的订单信息
        List<Order> allOrder = orderMapper.selectAllOKOrder();
        // 4. 获取所有的评论信息
        List<UserCommentVO> allComments = userCommentMapper.selectAllOKUserComment(null);
        // 5. 获取所有的用户信息
        List<User> allUsers = userMapper.selectAll(null);
        // 6. 获取所有的商品信息
        List<MedicinesVO> allMedicines = getMedicines(medicinesMapper.selectAll(null));

        // 定义一个存储每个商品和每个用户关系的List
        List<RelateDTO> data = new ArrayList<>();
        // 定义一个存储最后返回给前端的商品List
        List<Medicines> result = new ArrayList<>();


        // 开始计算每个商品和每个用户之间的关系数据
        for (Medicines medicines : allMedicines) {
            Integer medicinesId = medicines.getId();
            for (User user : allUsers) {
                Integer userId = user.getId();
                int index = 1;
                // 1. 判断该用户有没有收藏该商品，收藏的权重我们给 1
                Optional<Collect> collectOptional = allCollects.stream().filter(x -> x.getFid().equals(medicinesId) && x.getUserId().equals(userId)&&x.getModule().equals("MEDICINES")).findFirst();
                if (collectOptional.isPresent()) {
                    index += 1;
                }
                // 2. 判断该用户有没有给该商品加入购物车，加入购物车的权重我们给 2
                Optional<CartVO> cartOptional = allCarts.stream().filter(x -> x.getMedicinesId().equals(medicinesId) && x.getUserId().equals(userId)).findFirst();
                if (cartOptional.isPresent()) {
                    index += 2;
                }
                // 3. 判断该用户有没有对该商品下过单（已完成的订单），订单的权重我们给 3
                Optional<Order> orderOptional = allOrder.stream().filter(x -> x.getMedicinesId().equals(medicinesId) && x.getUserId().equals(userId)).findFirst();
                if (orderOptional.isPresent()) {
                    index += 3;
                }
                // 4. 判断该用户有没有对该商品评论过，评论的权重我们给 2
                Optional<UserCommentVO> commentOptional = allComments.stream().filter(x -> x.getMedicinesId().equals(medicinesId) && x.getUserId().equals(userId)).findFirst();
                if (commentOptional.isPresent()) {
                    index += 2;
                }
                if (index > 1) {
                    RelateDTO relateDTO = new RelateDTO(userId, medicinesId, index);
                    data.add(relateDTO);
                }
            }
        }
        // 数据准备结束后，就把这些数据一起喂给这个推荐算法
        List<Integer> medicinesIds = UserCF.recommend(currentUser.getId(), data);
        // 把商品id转换成商品
        List<Medicines> recommendResult = medicinesIds.stream().map(medicinesId -> allMedicines.stream()
                        .filter(x -> x.getId().equals(medicinesId)).findFirst().orElse(null))
                .limit(8).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(recommendResult) || recommendResult.size() < 8) {
            // 计算需要增加的商品数量
            int needToAdd = 8 - recommendResult.size();
            // 获取随机商品列表
            List<Medicines> randomMedicines = getRandomMedicines(needToAdd);
            // 将随机商品添加到推荐结果中
            recommendResult.addAll(randomMedicines);
        }
        // 如果推荐结果超过10个，可以随机移除一些商品以保持数量为10
        if (recommendResult.size() > 8) {
            // 移除多余的商品
            Collections.shuffle(recommendResult); // 随机打乱列表
            recommendResult.subList(8, recommendResult.size()).clear(); // 移除超出10个的商品
        }
        return recommendResult;
    }

    private List<Medicines> getRandomMedicines(int num) {
        List<Medicines> list = new ArrayList<>(num);
        List<MedicinesVO> medicines = getMedicines(medicinesMapper.selectAll(null));
        for (int i = 0; i < num; i++) {
            int index = new Random().nextInt(medicines.size());
            list.add(medicines.get(index));
        }
        return list;
    }

}
